//npm install crypto-js
import CryptoJS from "crypto-js";
import md5 from "js-md5";
const key = CryptoJS.enc.Utf8.parse("chinatowerenergy");

//说明：
//  1.如果加密解密涉及到前端和后端，则这里的key要保持和后端的key一致
//  2.AES的算法模式有好几种（ECB,CBC,CFB,OFB），所以也要和后端保持一致
//  3.AES的补码方式有两种（PKS5，PKS7），所以也要和后端保持一致
//  4.AES的密钥长度有三种（128,192,256，默认是128），所以也要和后端保持一致
//  5.AES的加密结果编码方式有两种（base64和十六进制），具体怎么选择由自己定，但是加密和解密的编码方式要统一
export default {
  /**
   * [encrypt 加密]
   * @return {[type]} [description]
   */
  encrypt(content) {
    return CryptoJS.AES.encrypt(content, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    }).toString();
  },
  /**
   * [decrypt 解密]
   * @return {[type]} [description]
   */
  decrypt(content) {
    const encryptedHexStr = CryptoJS.enc.Base64.parse(content);
    const encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    const decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });
    return decryptedData.toString(CryptoJS.enc.Utf8);
  },
  decryptHex(content) {
    if (content == null) {
      return "";
    }
    // 十六进制
    const encryptedHexStr = CryptoJS.enc.Hex.parse(content);
    const encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    const decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, key, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });
    return decryptedData.toString(CryptoJS.enc.Utf8);
  },
  getAesPhone(phone, header) {
    const aesKey = md5(phone).substring(10, 20) + header;
    return CryptoJS.AES.encrypt(phone, CryptoJS.enc.Utf8.parse(aesKey), {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    }).toString();
  },
  /**
   * 修复了安全热点伪随机数的问题
   * @param len
   * @returns {string}
   */
  randomCode(len = 6) {
    const arr = [
      "A",
      "B",
      "C",
      "D",
      "E",
      "F",
      "G",
      "H",
      "I",
      "J",
      "K",
      "L",
      "M",
      "N",
      "O",
      "P",
      "Q",
      "R",
      "S",
      "T",
      "U",
      "V",
      "W",
      "X",
      "Y",
      "Z",
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k",
      "l",
      "m",
      "n",
      "o",
      "p",
      "q",
      "r",
      "s",
      "t",
      "u",
      "v",
      "w",
      "x",
      "y",
      "z",
      0,
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9,
    ];
    const charsetLength = arr.length;
    let code = "";

    // 生成足够多的随机字节
    const randomBytes = new Uint8Array(len);
    window.crypto.getRandomValues(randomBytes);

    for (let i = 0; i < len; i++) {
      // 使用生成的随机字节作为索引（模字符集长度）
      const index = randomBytes[i] % charsetLength;
      code += arr[index];
    }
    return code;
  },
  aesEncrypt(data, k) {
    const _key = k
      ? CryptoJS.enc.Utf8.parse(k)
      : CryptoJS.enc.Utf8.parse(
          CryptoJS.enc.Base64.parse(process.env.VUE_APP_KEY).toString(
            CryptoJS.enc.Utf8
          )
        );
    const keyHex = CryptoJS.enc.Utf8.parse(_key);
    const encrypted = CryptoJS.AES.encrypt(data, keyHex, {
      mode: CryptoJS.mode.ECB,
      padding: CryptoJS.pad.Pkcs7,
    });

    const encryptData = encrypted.ciphertext.toString().toUpperCase();

    // 转为hex格式，转为Base64的字符串，如果转为base64格式，解密的方式就配置不同
    const hexStr = CryptoJS.enc.Hex.parse(encryptData);
    // 将密文转为Base64的字符串
    const base64Str = CryptoJS.enc.Base64.stringify(hexStr);
    return base64Str;
  },
  md5Enc(content) {
    return content ? CryptoJS.MD5(content).toString() : "";
  },
  decryptString(word) {
    let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
    let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    let decrypt = CryptoJS.AES.decrypt(srcs, key, {
      iv: CryptoJS.enc.Utf8.parse(""),
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7,
    });
    let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
    return decryptedStr.toString();
  },
};
